local Figure = require("app.figure.Figure")
local MapPoint = require("app.map.MapPoint")
local BgMap = require("app.map.BgMap")

local Monomer = class("Monomer", function()
    return display.newSprite()
end)

function Monomer:ctor()
    self.m_nMonomer = nil
    self.m_nDirection = FigureDirection.Down
    self.m_nState = FigureState.Stand
    self.m_bIsCanMoved = true
    self.m_runSpeed = 1
    self.m_visualRange = 5
    self.m_nTexturePathType = TexturePathType.Figure
    self.m_nCurRoleNum = 0
    self.hUpdateVertexZ = 0
    
    self:enableNodeEvents()
    self:setScale(1.0)
end

function Monomer:onEnter()
    self:showFigure()
end

function Monomer:onExit()
    self:stopAllActions()
end

-- 设置人物
function Monomer:setFigure(nType, nRoleNum)
    self.m_nTexturePathType = nType
    
    self.m_nCurRoleNum = nRoleNum
    
    if (self.m_nMonomer) then
        self:hideFigure()
        self:showFigure()
    end
end

-- 显示人物
function Monomer:showFigure()   
    if (self.m_nMonomer) then
        return
    end
    
    self.m_nMonomer = Figure.new(self.m_nTexturePathType, self.m_nCurRoleNum)
    self:setContentSize(self.m_nMonomer:getContentSize())
    self:setAnchorPoint(self.m_nMonomer:getAnchorPointWithFoot())
    local size = self:getContentSize()
    self.m_nMonomer:setPosition(size.width/2, size.height/2)
    self:addChild(self.m_nMonomer)
    self.m_nMonomer:setFigureState(self.m_nState, self.m_nDirection)
end

-- 隐藏人物
function Monomer:hideFigure()
    if (not self.m_nMonomer) then
        return
    end
    self.m_nMonomer:removeFromParent()
    self.m_nMonomer = nil
end

-- 设置人物面朝方向
function Monomer:setFrameDirection(nDirection)
    if (self.m_nMonomer) then
        self.m_nMonomer:setFrameDirection(nDirection)
    end
end

-- 设置人物状态
function Monomer:setFigureState(nState, nDirection)
    if (self.m_nState == FigureState.Death) then
        return
    end
    
    if (nState ~= FigureState.None) then
        self.m_nState = nState
    end
        
    if (nDirection ~= FigureDirection.None) then
        self.m_nDirection = nDirection
    end
        
    if (self.m_nMonomer) then
        self.m_nMonomer:setFigureState(nState, nDirection,self.m_nFrameDirection)
    end
end

function Monomer:getRect()
    local ptPos = cc.p(self:getPosition())
    local szContent = self:getContentSize()
    local ptAnchor = self:getAnchorPoint()
    
    local off_x = szContent.width * 0.4
    local off_y = szContent.height * ptAnchor.y * 0.5

    local width = szContent.width * 0.3
    local height = szContent.height * 0.6
    
    local rect = cc.rect(0,0,0,0)
    rect.x, rect.y = off_x, off_y
    rect.width, rect.height = width, height
    
    local x = szContent.width * ptAnchor.x
    local y = szContent.height * ptAnchor.y
    
    local point = cc.p(x, y)
    point = cc.pSub(ptPos, point)

    local relustRect = rect
    relustRect.x = point.x + rect.x
    relustRect.y = point.y + rect.y
    
    return relustRect
end

function Monomer:getAlphaWithPoint(point)
    return 0
end

-- 跑到左面
function Monomer:runLeft()
    self:setFigureState(FigureState.Run, FigureDirection.Left)
end

-- 跑到右面
function Monomer:runRight()
    self:setFigureState(FigureState.Run, FigureDirection.Right)
end

-- 跑到上面
function Monomer:runUp()
    self:setFigureState(FigureState.Run, FigureDirection.Up)
end

-- 跑到下面
function Monomer:runDown()
    self:setFigureState(FigureState.Run, FigureDirection.Down)
end

-- 跑到左上
function Monomer:runLeftAndUp()
    self:setFigureState(FigureState.Run, FigureDirection.LeftAndUp)
end

-- 跑到右上
function Monomer:runRightAndUp()
    self:setFigureState(FigureState.Run, FigureDirection.RightAndUp)
end

-- 跑到右下
function Monomer:runRightAndDown()
    self:setFigureState(FigureState.Run, FigureDirection.RightAndDown)
end

-- 跑到左下
function Monomer:runLeftAndDown()
    self:setFigureState(FigureState.Run, FigureDirection.LeftAndDown)
end

-- 面朝左
function Monomer:faceLeft()
    self:setFrameDirection(FigureFrameDirection.Left)
end

-- 面朝上
function Monomer:faceUp()
    self:setFrameDirection(FigureFrameDirection.Up)
end

-- 面朝右
function Monomer:faceRight()
    self:setFrameDirection(FigureFrameDirection.Right)
end

-- 面朝下
function Monomer:faceDown()
    self:setFrameDirection(FigureFrameDirection.Down)
end

function Monomer:stand()
    self:setFigureState(FigureState.Stand, FigureDirection.None)
end

function Monomer:isInTheFieldOfView(monomer)
    local pos1 = cc.p(self:getPosition())
    local pos2 = cc.p(monomer:getPosition())
    
    local mpos1 = MapPoint.new(pos1)
    local mpos2 = MapPoint.new(pos2)
    
    if (mpos1:getDistance(mpos2) <= self.m_visualRange) then
        return true
    end
    
    return false
end

function Monomer:isMoveRunning()
    --当前点到格子中点的距离
    local x, y = self:getPosition()
    local pos = cc.p(x, y)
    local mpos = MapPoint.new(pos)
    local pos2 = mpos:getCCPointValue()
    return (cc.pGetDistance(mpos:getCCPointValue(), pos) >= math.sqrt(math.pow(mpos.getGridSize().width/2,2)+math.pow(mpos.getGridSize().height/2,2)))
end

function Monomer:actionsWithPoint(startMPoint, endMPoint)
    local callFunc0 = nil
    local callFunc = nil
    
    local array = {}
    
    if (startMPoint:equalsObj(endMPoint)) then
        return array
    end
    
    local lenghtX = endMPoint.x - startMPoint.x
    local lenghtY = endMPoint.z - startMPoint.z
    local lenght = math.sqrt(lenghtX * lenghtX + lenghtY * lenghtY)
    
    local gridNumber = startMPoint:getDistance(endMPoint)
    
    local fTime = 0.6 * startMPoint:getDistance(endMPoint) / self.m_runSpeed / gridNumber

    local pointX = lenghtX / lenght
    local pointY = lenghtY / lenght

    local angle_X = math.acos(pointX) * 180 / math.pi
    local angle_Y = math.acos(pointY) * 180 / math.pi
    
    local angle = angle_X
    if (angle_Y > 90) then
        angle = 360 - angle_X
    end
    
    local nType = math.floor(((angle + 22.5) % 360 ) / 45.0)
    local freDirt = FigureFrameDirection.Down
    if (self.m_nMonomer) then
        local fType = math.floor(((angle + 45) % 360 ) / 90)
        if fType == 0 then
            callFunc0 = cc.CallFunc:create(handler(self, self.faceRight))
        elseif fType == 1 then
            callFunc0 = cc.CallFunc:create(handler(self, self.faceUp))
        elseif fType == 2 then
            callFunc0 = cc.CallFunc:create(handler(self, self.faceLeft))
        elseif fType == 3 then
            callFunc0 = cc.CallFunc:create(handler(self, self.faceDown))
        end        
    end
    

    if (nType == 0) then
        callFunc = cc.CallFunc:create(handler(self, self.runRight))
    elseif (nType == 1) then
        callFunc = cc.CallFunc:create(handler(self, self.runRightAndUp))
    elseif (nType == 2) then
        callFunc = cc.CallFunc:create(handler(self, self.runUp))
    elseif (nType == 3) then
        callFunc = cc.CallFunc:create(handler(self, self.runLeftAndUp))
    elseif (nType == 4) then
        callFunc = cc.CallFunc:create(handler(self, self.runLeft))
    elseif (nType == 5) then
        callFunc = cc.CallFunc:create(handler(self, self.runLeftAndDown))
    elseif (nType == 6) then
        callFunc = cc.CallFunc:create(handler(self, self.runDown))
    elseif (nType == 7) then
        callFunc = cc.CallFunc:create(handler(self, self.runRightAndDown))
    end

    
    table.insert(array, callFunc0)
    table.insert(array, callFunc)
    
    local moveTo = cc.MoveTo:create(fTime, endMPoint:getCCPointValue())
    table.insert(array, moveTo)

    return array
end

function Monomer:actionsWithMoveTo(dequeMapPoint)
    local array = {}
    
    if (#dequeMapPoint <= 1) then
        return array
    end
    
    local callFunc1 = cc.CallFunc:create(handler(self, self.setTimer_UpdateVertexZ))
    local callFunc2 = cc.CallFunc:create(handler(self, self.killTimer_UpdateVertexZ))

    table.insert(array, callFunc1)
        
    for i = 2, #dequeMapPoint do
        local startMPoint = dequeMapPoint[i-1]
        local endMPoint = dequeMapPoint[i]
        local array2 = self:actionsWithPoint(startMPoint, endMPoint)
        for j = 1, #array2 do
            table.insert(array, array2[j])
        end
    end
    
    table.insert(array, callFunc2)
            
    return array
end

-- 去到指定点
function Monomer:goTo(mpoint)
    local pos = cc.p(self:getPosition())
    local relust = MoveInfo.new(0.0, MapPoint.new(pos), false)
    
    if (self.m_bIsCanMoved == false) then
        return relust
    end
    
    local nState = self:getState()
    if (nState == FigureState.Death or 
        nState == FigureState.Attack or
        nState == FigureState.Caster or
        nState == FigureState.Hurt) then
        return relust
    end
    
    if (self:isMoveRunning()) then
        return relust
    end
    
    self:stopActionByTag(TAG_MOVET)
    self:stopActionByTag(TAG_FOLLOWATTACK)
    self:stopActionByTag(TAG_COOLINGTIMEATTACK)
        
    local begin = MapPoint.new(pos)
    local dequeMPoint = MapController:getPath(begin, mpoint)
        
    if (#dequeMPoint <= 1) then
        self:stand()
        relust.bIsCanNotFineTheWay = true
        return relust
    end
        
    local array = self:actionsWithMoveTo(dequeMPoint)
        
    local callFunc = cc.CallFunc:create(handler(self, self.goBegin))
    local callFunc2 = cc.CallFunc:create(handler(self, self.goEnd))
    table.insert(array, 1, callFunc)
    table.insert(array, callFunc2)
    local sequence = cc.Sequence:create(array)
    sequence:setTag(TAG_MOVET)
    self:runAction(sequence)
        
    relust.fTime = sequence:getDuration()
    relust.mpoint = dequeMPoint[#dequeMPoint]

    return relust
end

-- 启动更新Z轴计时器
function Monomer:setTimer_UpdateVertexZ()
    self:killTimer_UpdateVertexZ()
    self.hUpdateVertexZ = cc.Director:getInstance():getScheduler():scheduleScriptFunc(handler(self, self.updateVertexZ), 0, false)
end

-- 关闭更新Z轴计时器
function Monomer:killTimer_UpdateVertexZ()
    if (self.hUpdateVertexZ) then
        cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.hUpdateVertexZ)
        self.hUpdateVertexZ = nil
    end
end

-- 更新Z轴计时器回调函数
function Monomer:updateVertexZ(fDelay)
    local point = cc.p(self:getPosition())
    local value = BgMap.getZOrder(point) -- z轴
    self:setLocalZOrder(value)
    
    if (not self.m_nMonomer) then
        return
    end
        
    if (MapController:getCurMap():getCurrentGridValue(MapPoint.new(point)) == 2) then
        if (self.m_nMonomer:getOpacity() == 128) then
            return
        end
            
        self.m_nMonomer:setOpacityEx(128)
        self.m_nMonomer:setColor(cc.c3b(166,166,166))
    else
        if (self.m_nMonomer:getOpacity() == 255) then
            return
        end
            
        self.m_nMonomer:setOpacityEx(255)
        self.m_nMonomer:setColor(cc.c3b(255,255,255))
    end
end

function Monomer:goBegin()

end

function Monomer:goEnd()
    self:stand()
end

-- 根据指定角度获取方向
function Monomer:getDirectionType(fAngle)
    local nDirection = FigureDirection.None
    
    local nType = math.floor(((math.floor(fAngle + 22.5)) % 360 ) / 45.0)
    
    if (nType == 0) then
        nDirection = FigureDirection.Right
    elseif (nType == 1) then
        nDirection = FigureDirection.RightAndUp
    elseif (nType == 2) then
        nDirection = FigureDirection.Up
    elseif (nType == 3) then
        nDirection = FigureDirection.LeftAndUp
    elseif (nType == 4) then
        nDirection = FigureDirection.Left
    elseif (nType == 5) then
        nDirection = FigureDirection.LeftAndDown
    elseif (nType == 6) then
        nDirection = FigureDirection.Down
    elseif (nType == 7) then
        nDirection = FigureDirection.RightAndDown
    end

    return nDirection
end

function Monomer:getFigure()
    return self.m_nMonomer
end

function Monomer:getState()
    return self.m_nState
end

function Monomer:getDirection()
    return self.m_nDirection
end

function Monomer:getCanMoved()
    return self.m_isCanMoved
end

function Monomer:setCanMoved(bCanMoved)
    self.m_isCanMoved = bCanMoved
end

function Monomer:getRunSpeed()
    return self.m_runSpeed
end

function Monomer:setRunSpeed(runSpeed)
    self.m_runSpeed = runSpeed
end

function Monomer:getVisualRange()
    return self.m_visualRange
end

function Monomer:setVisualRange(visualRange)
    self.m_visualRange = visualRange
end

function Monomer:getCurrGrid()
    return MapPoint.new(cc.p(self:getPosition()))
end

function Monomer:setOpacityEx(opacity)
    self.m_nMonomer:setOpacity(opacity)
end

function Monomer:getOpacityEx(opacity)
    return self.m_nMonomer:getOpacity()
end

cc.exports.Monomer = Monomer
return Monomer